# -*- coding: utf-8 -*-
"""
Side-Channel Analysis 101
2. differential power analysis on DES hardware implementation
DPA contest v1
lasf modified 2022.04.26
----------------------------------------------------
Sunghyun Jin
sunghyunjin@korea.ac.kr
https://sunghyunjin.com
Cryptographic Algorithm Lab.
School of Cyber Security,
Korea University,
Republic of Korea
Center for Information Security Technologies (CIST),
Institute of Cyber Security & Privacy (ICSP),
Korea University,
Republic of Korea
----------------------------------------------------
"""
print('')
import struct
import os
import h5py
import numpy as np
import scipy.io as spio
import tqdm
import matplotlib.pyplot as plt
%matplotlib inline
from bokeh.plotting import figure, show
from bokeh.io import output_notebook
from bokeh.resources import INLINE
from bokeh.models import Span
from bokeh.palettes import Spectral11
output_notebook(INLINE)
def check_file_exists(file_path, verbose = True):
if os.path.exists(file_path) == False:
if verbose:
print("Error: provided file path '%s' does not exist!" % file_path)
return False
if verbose:
print("EXIST :", file_path)
return True
fpath = '../dataset'
fname = fpath + '/secmatv1_2006_04_0809.h5'
if check_file_exists(fname):
h5f = h5py.File(fname, 'r')
print(list(h5f.keys()))
print('traces :', h5f['traces'].shape)
print('plaintext :', h5f['plaintext'].shape)
print('ciphertext :', h5f['ciphertext'].shape)
print('key :', h5f['key'].shape)
tr = h5f['traces'][:]
pt = h5f['plaintext'][:]
pt = pt.astype(np.uint8)
ct = h5f['ciphertext'][:]
ct = ct.astype(np.uint8)
key = h5f['key'][0]
key = key.astype(np.uint8)
h5f.close()
EXIST : ../dataset/secmatv1_2006_04_0809.h5 ['ciphertext', 'key', 'plaintext', 'traces'] traces : (3085, 20003) plaintext : (3085, 8) ciphertext : (3085, 8) key : (1, 8)
print('key :', ['%02X' % i for i in key])
key : ['6A', '65', '78', '6A', '65', '78', '6A', '65']
plt.plot(tr[0])
plt.show()
deltaplot = figure(plot_width=800)
deltaplot.title.text = 'A total power consumption trace'
deltaplot.title.align = 'center'
deltaplot.title.text_font_size = '25px'
deltaplot.xaxis.axis_label = 'time'
deltaplot.yaxis.axis_label = 'power'
xrange = list(range(tr.shape[1]))
deltaplot.line(xrange, tr[0,:])
show(deltaplot)
num = 20
deltaplot = figure(plot_width=800)
deltaplot.title.text = '%d power consumption traces' % num
deltaplot.title.align = 'center'
deltaplot.title.text_font_size = '25px'
deltaplot.xaxis.axis_label = 'time'
deltaplot.yaxis.axis_label = 'power'
xrange = list(range(tr.shape[1]))
for i, t in enumerate(tr[:num]):
deltaplot.line(xrange, t, color = Spectral11[i % len(Spectral11)])
show(deltaplot)
deltaplot = figure(plot_width=800)
deltaplot.title.text = 'mean trace'
deltaplot.title.align = 'center'
deltaplot.title.text_font_size = '25px'
deltaplot.xaxis.axis_label = 'time'
deltaplot.yaxis.axis_label = 'power'
xrange = list(range(tr.shape[1]))
deltaplot.line(xrange, np.mean(tr, axis=0))
show(deltaplot)
deltaplot = figure(plot_width=800)
deltaplot.title.text = 'variance trace'
deltaplot.title.align = 'center'
deltaplot.title.text_font_size = '25px'
deltaplot.xaxis.axis_label = 'time'
deltaplot.yaxis.axis_label = 'power'
xrange = list(range(tr.shape[1]))
deltaplot.line(xrange, np.var(tr, axis=0))
show(deltaplot)
ith = 0
tmp = np.vectorize((lambda x: (x >> 7) & 0x1))(pt[:,0])
ind1 = np.where(tmp == 0)[0]
ind2 = np.where(tmp != 0)[0]
print('#MSB(0/1) -> {} : {}'.format(ind1.shape[0], ind2.shape[0]))
#MSB(0/1) -> 1500 : 1585
dom = np.mean(tr[ind1,:], axis = 0) - np.mean(tr[ind2], axis = 0)
deltaplot = figure(plot_width=800)
deltaplot.title.text = 'Difference of Mean'
deltaplot.title.align = 'center'
deltaplot.title.text_font_size = '25px'
deltaplot.xaxis.axis_label = 'time'
deltaplot.yaxis.axis_label = 'difference'
xrange = list(range(dom.shape[0]))
deltaplot.line(xrange, dom)
show(deltaplot)
from des import DES
def calculate_dom_hd_lr(tr, pt, ithbit):
des = DES()
ptb = np.unpackbits(pt, axis = 1)
buf_ip = np.zeros(ptb.shape, dtype = np.uint8)
for i, j in enumerate(des.PI):
buf_ip[:,i] = ptb[:,j-1]
L = buf_ip[:,:32]
R = buf_ip[:,32:]
#tmp = np.vectorize((lambda x: (x >> bit) & 0x1))(pt[:,ith])
tmp = np.vectorize((lambda x: (x >> ithbit) & 0x1))(L[:,ithbit] ^ R[:,ithbit])
ind1 = np.where(tmp == 0)[0]
ind2 = np.where(tmp != 0)[0]
dom = np.mean(tr[ind1,:], axis = 0) - np.mean(tr[ind2,:], axis = 0)
return dom
dom_hd_lr = np.zeros((32, tr.shape[1]), dtype = np.double)
for ind, ithbit in enumerate(tqdm.tqdm(range(32))):
dom_hd_lr[ind, :] = calculate_dom_hd_lr(tr, pt, ithbit)
0%| | 0/32 [00:00<?, ?it/s]/opt/homebrew/Caskroom/miniforge/base/envs/hw/lib/python3.9/site-packages/numpy/core/fromnumeric.py:3474: RuntimeWarning: Mean of empty slice. return _methods._mean(a, axis=axis, dtype=dtype, /opt/homebrew/Caskroom/miniforge/base/envs/hw/lib/python3.9/site-packages/numpy/core/_methods.py:181: RuntimeWarning: invalid value encountered in true_divide ret = um.true_divide( 100%|███████████████████████████████████████████| 32/32 [00:01<00:00, 24.39it/s]
#num = 8
num = dom_hd_lr.shape[0]
deltaplot = figure(plot_width=800)
deltaplot.title.text = '%d Difference of Mean' % num
deltaplot.title.align = 'center'
deltaplot.title.text_font_size = '25px'
deltaplot.xaxis.axis_label = 'time'
deltaplot.yaxis.axis_label = 'diff'
xrange = list(range(dom_hd_lr.shape[1]))
for i, t in enumerate(dom_hd_lr[:num]):
deltaplot.line(xrange, t, color = Spectral11[i % len(Spectral11)])
show(deltaplot)